"Fossies" - the Fresh Open Source Software Archive

Member "memcached-1.6.15/cache.c" (21 Feb 2022, 3366 Bytes) of package /linux/www/memcached-1.6.15.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "cache.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.6.12_vs_1.6.13.

    1 /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
    2 #include <stdlib.h>
    3 #include <string.h>
    4 #include <inttypes.h>
    5 #include <assert.h>
    6 
    7 #ifndef NDEBUG
    8 #include <signal.h>
    9 #endif
   10 
   11 #include "cache.h"
   12 
   13 #ifndef NDEBUG
   14 const uint64_t redzone_pattern = 0xdeadbeefcafedeed;
   15 int cache_error = 0;
   16 #endif
   17 
   18 cache_t* cache_create(const char *name, size_t bufsize, size_t align) {
   19     cache_t* ret = calloc(1, sizeof(cache_t));
   20     char* nm = strdup(name);
   21     if (ret == NULL || nm == NULL ||
   22         pthread_mutex_init(&ret->mutex, NULL) == -1) {
   23         free(ret);
   24         free(nm);
   25         return NULL;
   26     }
   27 
   28     ret->name = nm;
   29     STAILQ_INIT(&ret->head);
   30 
   31 #ifndef NDEBUG
   32     ret->bufsize = bufsize + 2 * sizeof(redzone_pattern);
   33 #else
   34     ret->bufsize = bufsize;
   35 #endif
   36     assert(ret->bufsize >= sizeof(struct cache_free_s));
   37 
   38     return ret;
   39 }
   40 
   41 void cache_set_limit(cache_t *cache, int limit) {
   42     pthread_mutex_lock(&cache->mutex);
   43     cache->limit = limit;
   44     pthread_mutex_unlock(&cache->mutex);
   45 }
   46 
   47 static inline void* get_object(void *ptr) {
   48 #ifndef NDEBUG
   49     uint64_t *pre = ptr;
   50     return pre + 1;
   51 #else
   52     return ptr;
   53 #endif
   54 }
   55 
   56 void cache_destroy(cache_t *cache) {
   57     while (!STAILQ_EMPTY(&cache->head)) {
   58         struct cache_free_s *o = STAILQ_FIRST(&cache->head);
   59         STAILQ_REMOVE_HEAD(&cache->head, c_next);
   60         free(o);
   61     }
   62     free(cache->name);
   63     pthread_mutex_destroy(&cache->mutex);
   64     free(cache);
   65 }
   66 
   67 void* cache_alloc(cache_t *cache) {
   68     void *ret;
   69     pthread_mutex_lock(&cache->mutex);
   70     ret = do_cache_alloc(cache);
   71     pthread_mutex_unlock(&cache->mutex);
   72     return ret;
   73 }
   74 
   75 void* do_cache_alloc(cache_t *cache) {
   76     void *ret;
   77     void *object;
   78     if (cache->freecurr > 0) {
   79         ret = STAILQ_FIRST(&cache->head);
   80         STAILQ_REMOVE_HEAD(&cache->head, c_next);
   81         object = get_object(ret);
   82         cache->freecurr--;
   83     } else if (cache->limit == 0 || cache->total < cache->limit) {
   84         object = ret = malloc(cache->bufsize);
   85         if (ret != NULL) {
   86             object = get_object(ret);
   87 
   88             cache->total++;
   89         }
   90     } else {
   91         object = NULL;
   92     }
   93 
   94 #ifndef NDEBUG
   95     if (object != NULL) {
   96         /* add a simple form of buffer-check */
   97         uint64_t *pre = ret;
   98         *pre = redzone_pattern;
   99         ret = pre+1;
  100         memcpy(((char*)ret) + cache->bufsize - (2 * sizeof(redzone_pattern)),
  101                &redzone_pattern, sizeof(redzone_pattern));
  102     }
  103 #endif
  104 
  105     return object;
  106 }
  107 
  108 void cache_free(cache_t *cache, void *ptr) {
  109     pthread_mutex_lock(&cache->mutex);
  110     do_cache_free(cache, ptr);
  111     pthread_mutex_unlock(&cache->mutex);
  112 }
  113 
  114 void do_cache_free(cache_t *cache, void *ptr) {
  115 #ifndef NDEBUG
  116     /* validate redzone... */
  117     if (memcmp(((char*)ptr) + cache->bufsize - (2 * sizeof(redzone_pattern)),
  118                &redzone_pattern, sizeof(redzone_pattern)) != 0) {
  119         raise(SIGABRT);
  120         cache_error = 1;
  121         return;
  122     }
  123     uint64_t *pre = ptr;
  124     --pre;
  125     if (*pre != redzone_pattern) {
  126         raise(SIGABRT);
  127         cache_error = -1;
  128         return;
  129     }
  130     ptr = pre;
  131 #endif
  132     if (cache->limit != 0 && cache->limit < cache->total) {
  133         free(ptr);
  134         cache->total--;
  135     } else {
  136         STAILQ_INSERT_HEAD(&cache->head, (struct cache_free_s *)ptr, c_next);
  137         cache->freecurr++;
  138     }
  139 }
  140