• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

ink_memory.cc

Go to the documentation of this file.
00001 /** @file
00002 
00003   Memory allocation routines for libts
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 #include "libts.h"
00024 
00025 #include <assert.h>
00026 #if defined(linux)
00027 // XXX: SHouldn't that be part of CPPFLAGS?
00028 #ifndef _XOPEN_SOURCE
00029 #define _XOPEN_SOURCE 600
00030 #endif
00031 #endif
00032 #include <stdlib.h>
00033 #include <string.h>
00034 
00035 void *
00036 ats_malloc(size_t size)
00037 {
00038   void *ptr = NULL;
00039 
00040   /*
00041    * There's some nasty code in libts that expects
00042    * a MALLOC of a zero-sized item to work properly. Rather
00043    * than allocate any space, we simply return a NULL to make
00044    * certain they die quickly & don't trash things.
00045    */
00046 
00047   // Useful for tracing bad mallocs
00048   // ink_stack_trace_dump();
00049   if (likely(size > 0)) {
00050     if (unlikely((ptr = malloc(size)) == NULL)) {
00051       ink_stack_trace_dump();
00052       ink_fatal(1, "ats_malloc: couldn't allocate %zu bytes", size);
00053     }
00054   }
00055   return ptr;
00056 }                               /* End ats_malloc */
00057 
00058 void *
00059 ats_calloc(size_t nelem, size_t elsize)
00060 {
00061   void *ptr = calloc(nelem, elsize);
00062   if (unlikely(ptr == NULL)) {
00063     ink_stack_trace_dump();
00064     ink_fatal(1, "ats_calloc: couldn't allocate %zu %zu byte elements", nelem, elsize);
00065   }
00066   return ptr;
00067 }                               /* End ats_calloc */
00068 
00069 void *
00070 ats_realloc(void *ptr, size_t size)
00071 {
00072   void *newptr = realloc(ptr, size);
00073   if (unlikely(newptr == NULL)) {
00074     ink_stack_trace_dump();
00075     ink_fatal(1, "ats_realloc: couldn't reallocate %zu bytes", size);
00076   }
00077   return newptr;
00078 }                               /* End ats_realloc */
00079 
00080 // TODO: For Win32 platforms, we need to figure out what to do with memalign.
00081 // The older code had ifdef's around such calls, turning them into ats_malloc().
00082 void *
00083 ats_memalign(size_t alignment, size_t size)
00084 {
00085   void *ptr;
00086 
00087 #if HAVE_POSIX_MEMALIGN || TS_HAS_JEMALLOC
00088   if (alignment <= 8)
00089     return ats_malloc(size);
00090 
00091 #if defined(openbsd)
00092   if (alignment > PAGE_SIZE)
00093       alignment = PAGE_SIZE;
00094 #endif
00095 
00096   int retcode = posix_memalign(&ptr, alignment, size);
00097 
00098   if (unlikely(retcode)) {
00099     if (retcode == EINVAL) {
00100       ink_fatal(1, "ats_memalign: couldn't allocate %zu bytes at alignment %zu - invalid alignment parameter",
00101                 size, alignment);
00102     } else if (retcode == ENOMEM) {
00103       ink_fatal(1, "ats_memalign: couldn't allocate %zu bytes at alignment %zu - insufficient memory",
00104                 size, alignment);
00105     } else {
00106       ink_fatal(1, "ats_memalign: couldn't allocate %zu bytes at alignment %zu - unknown error %d",
00107                 size, alignment, retcode);
00108     }
00109   }
00110 #else
00111   ptr = memalign(alignment, size);
00112   if (unlikely(ptr == NULL)) {
00113     ink_fatal(1, "ats_memalign: couldn't allocate %zu bytes at alignment %zu",  size,  alignment);
00114   }
00115 #endif
00116   return ptr;
00117 }                               /* End ats_memalign */
00118 
00119 void
00120 ats_free(void *ptr)
00121 {
00122   if (likely(ptr != NULL))
00123     free(ptr);
00124 }                               /* End ats_free */
00125 
00126 void*
00127 ats_free_null(void *ptr)
00128 {
00129   if (likely(ptr != NULL))
00130     free(ptr);
00131   return NULL;
00132 }                               /* End ats_free_null */
00133 
00134 void
00135 ats_memalign_free(void *ptr)
00136 {
00137   if (likely(ptr))
00138     free(ptr);
00139 }
00140 
00141 // This effectively makes mallopt() a no-op (currently) when tcmalloc
00142 // or jemalloc is used. This might break our usage for increasing the
00143 // number of mmap areas (ToDo: Do we still really need that??).
00144 //
00145 // TODO: I think we might be able to get rid of this?
00146 int
00147 ats_mallopt(int param ATS_UNUSED, int value ATS_UNUSED)
00148 {
00149 #if TS_HAS_JEMALLOC
00150 // TODO: jemalloc code ?
00151 #else
00152 #if TS_HAS_TCMALLOC
00153 // TODO: tcmalloc code ?
00154 #else
00155 #if defined(linux)
00156   return mallopt(param, value);
00157 #endif // ! defined(linux)
00158 #endif // ! TS_HAS_TCMALLOC
00159 #endif // ! TS_HAS_JEMALLOC
00160   return 0;
00161 }
00162 
00163 int
00164 ats_msync(caddr_t addr, size_t len, caddr_t end, int flags)
00165 {
00166   size_t pagesize = ats_pagesize();
00167 
00168   // align start back to page boundary
00169   caddr_t a = (caddr_t) (((uintptr_t) addr) & ~(pagesize - 1));
00170   // align length to page boundry covering region
00171   size_t l = (len + (addr - a) + (pagesize - 1)) & ~(pagesize - 1);
00172   if ((a + l) > end)
00173     l = end - a;                // strict limit
00174 #if defined(linux)
00175 /* Fix INKqa06500
00176    Under Linux, msync(..., MS_SYNC) calls are painfully slow, even on
00177    non-dirty buffers. This is true as of kernel 2.2.12. We sacrifice
00178    restartability under OS in order to avoid a nasty performance hit
00179    from a kernel global lock. */
00180 #if 0
00181   // this was long long ago
00182   if (flags & MS_SYNC)
00183     flags = (flags & ~MS_SYNC) | MS_ASYNC;
00184 #endif
00185 #endif
00186   int res = msync(a, l, flags);
00187   return res;
00188 }
00189 
00190 int
00191 ats_madvise(caddr_t addr, size_t len, int flags)
00192 {
00193 #if defined(linux)
00194   (void) addr;
00195   (void) len;
00196   (void) flags;
00197   return 0;
00198 #else
00199   size_t pagesize = ats_pagesize();
00200   caddr_t a = (caddr_t) (((uintptr_t) addr) & ~(pagesize - 1));
00201   size_t l = (len + (addr - a) + pagesize - 1) & ~(pagesize - 1);
00202   int res = 0;
00203 #if HAVE_POSIX_MADVISE
00204   res = posix_madvise(a, l, flags);
00205 #else
00206   res = madvise(a, l, flags);
00207 #endif
00208   return res;
00209 #endif
00210 }
00211 
00212 int
00213 ats_mlock(caddr_t addr, size_t len)
00214 {
00215   size_t pagesize = ats_pagesize();
00216 
00217   caddr_t a = (caddr_t) (((uintptr_t) addr) & ~(pagesize - 1));
00218   size_t l = (len + (addr - a) + pagesize - 1) & ~(pagesize - 1);
00219   int res = mlock(a, l);
00220   return res;
00221 }
00222 
00223 
00224 /*-------------------------------------------------------------------------
00225   Moved from old ink_resource.h
00226   -------------------------------------------------------------------------*/
00227 char *
00228 _xstrdup(const char *str, int length, const char* /* path ATS_UNUSED */)
00229 {
00230   char *newstr;
00231 
00232   if (likely(str)) {
00233     if (length < 0)
00234       length = strlen(str);
00235 
00236     newstr = (char *)ats_malloc(length + 1);
00237     ink_strlcpy(newstr, str, length + 1);
00238     return newstr;
00239   }
00240   return NULL;
00241 }

Generated by  doxygen 1.7.1